home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 076-100 / scopedisk100 / lhwarp / lhwarp.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  25KB  |  989 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <exec/io.h>
  4. #include <devices/trackdisk.h>
  5. #include <libraries/dos.h>
  6. #include <libraries/dosextens.h>
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <proto/exec.h>
  10. #include <proto/dos.h>
  11.  
  12.  
  13. /* Lhwarp version 1.03 */
  14. #define MAJOR_VERSION 1
  15. #define MINOR_VERSION 0
  16. #define DECIMAL_VERSION 3
  17.  
  18.  
  19. #define NUM_HEADS 2
  20.  
  21.  
  22. #define TRACK_SIZE (TD_SECTOR * NUMSECS * NUM_HEADS)
  23.  
  24.  
  25. #define SEEK_SET 0
  26.  
  27.  
  28. #define WARP_READ 1
  29. #define WARP_WRITE 2
  30.  
  31.  
  32. #define IN_BUFFER_SIZE 16384
  33. #define OUT_BUFFER_SIZE 16384
  34.  
  35.  
  36. /* Only LZHUF is supported at the moment */
  37. #define COMPTYPE_LHARC 0
  38.  
  39.  
  40. /* Note, this has changed! */
  41. #define DATATYPE_NORMAL 0
  42. #define DATATYPE_RAW 1
  43.  
  44.  
  45. struct WarpHeader
  46.    {
  47.       UBYTE  MajorVersion;
  48.       UBYTE  MinorVersion;
  49.       UBYTE  DecimalVersion;
  50.       UBYTE  Reserved;
  51.       USHORT StartTrack;
  52.       USHORT EndTrack;
  53.       ULONG  TextLength;
  54.       ULONG  CompressedTextLength;
  55.    };
  56.  
  57.  
  58. struct CompHeader101
  59.    {
  60.       UBYTE  CompressionType;
  61.       UBYTE  DataType;
  62.       UBYTE  TrackNumber;
  63.       UBYTE  Unused;
  64.       ULONG  FullLength;
  65.       ULONG  CompressedLength;
  66.    };
  67.  
  68.  
  69. struct CompHeader102
  70.    {
  71.       UBYTE  CompressionType;
  72.       UBYTE  DataType;
  73.       UBYTE  TrackNumber;
  74.       UBYTE  Unused;
  75.       ULONG  FullLength;
  76.       ULONG  CompressedLength;
  77.       ULONG  CheckSum;
  78.    };
  79.  
  80.  
  81. #define LABEL_LENGTH (16 * NUMSECS * NUM_HEADS)
  82.  
  83.  
  84. UBYTE *iotd_SecLabel = NULL;
  85.  
  86.  
  87. struct WarpHeader WHeader;
  88. struct IOExtTD *ReadMsg   = NULL;
  89. struct IOExtTD *WriteMsg  = NULL;
  90. struct MsgPort *ReadPort  = NULL;
  91. struct MsgPort *WritePort = NULL;
  92.  
  93.  
  94. extern FILE  *infile;
  95. extern FILE  *outfile;
  96. extern UBYTE *FilePosition;
  97. extern UBYTE *EndOfFilePosition;
  98. extern UBYTE *PutFilePosition;
  99.  
  100.  
  101. /* LZHUF defines and externs */
  102. #define N        4096    /* Size of string buffer */
  103. #define F        60    /* Size of look-ahead buffer */
  104. #define THRESHOLD    2
  105. #define NIL        N    /* End of tree's node  */
  106.  
  107. extern unsigned char *text_buf;
  108. extern short         *lson, *rson, *dad;
  109.  
  110.  
  111. struct CompHeader101 CHeader101;
  112. struct CompHeader102 CHeader102;
  113. char               FileName[256];
  114. char               TextFileName[256];
  115. UBYTE              Command;
  116. UBYTE              AppendTextFile;
  117. UBYTE              Version101;
  118. BPTR               FHandle;
  119. ULONG              StartTrack;
  120. ULONG              EndTrack;
  121. ULONG              Unit;
  122. APTR               DataBlock = NULL;
  123. APTR               NewBlock = NULL;
  124. APTR               TrackdiskBlock = NULL;
  125.  
  126.  
  127. ULONG GetFileLength(register char *FileToOpen);
  128. ULONG DoSum(UBYTE *Block, ULONG Length);
  129. void  __regargs Decode(ULONG Size);
  130.  
  131.  
  132. void main(int argc, char **argv)
  133. {
  134.    if (argc != 2 && argc != 4 && argc != 6 && argc != 7)
  135.       {
  136.          Title();
  137.          exit (1);
  138.       }
  139.  
  140.    if (!stricmp(argv[1], "READ"))
  141.       {
  142.          /* Remove the file if it was already there */
  143.          remove(FileName);
  144.  
  145.          Command = WARP_READ;
  146.       }
  147.    else if (!stricmp(argv[1], "WRITE"))
  148.       {
  149.          Command = WARP_WRITE;
  150.       }
  151.    else if (!stricmp(argv[1], "HELP"))
  152.       {
  153.          exit(0);
  154.       }
  155.    else
  156.       {
  157.          puts("\nUnknown command\n");
  158.          exit(1);
  159.       }
  160.  
  161.    if (argc < 6 && Command == WARP_READ)
  162.       {
  163.          Title();
  164.          exit (1);
  165.       }
  166.  
  167.    if (argc == 7)
  168.       {
  169.          strcpy(TextFileName, argv[6]);
  170.          AppendTextFile = 1;
  171.       }
  172.    else
  173.       {
  174.          AppendTextFile = 0;
  175.       }
  176.  
  177.    /* Get the unit number */
  178.    Unit       = atoi(argv[2]);
  179.  
  180.    /* Get the file name */
  181.    strcpy(FileName, argv[3]);
  182.    strupr(FileName);
  183.  
  184.    /* Append .LHW if necessary */
  185.    if (strcmp(FileName, ".LHW"))
  186.       {
  187.          if (strlen(FileName) > 4)
  188.             {
  189.                if (strcmp(&FileName[strlen(FileName)-4], ".LHW"))
  190.                   {
  191.                      strcat(FileName, ".LHW");
  192.                   }
  193.             }
  194.          else
  195.             {
  196.                strcat(FileName, ".LHW");
  197.             }
  198.       }
  199.  
  200.    /* Get the start and end tracks */
  201.    if (argc > 5)
  202.       {
  203.          StartTrack = atoi(argv[4]);
  204.          EndTrack   = atoi(argv[5]);
  205.       }
  206.  
  207.    if (StartTrack > EndTrack)
  208.       {
  209.          puts("Start track is greater than end track\n");
  210.          exit (1);
  211.       }
  212.  
  213.    Init();
  214.  
  215.    if (Command == WARP_WRITE)
  216.       {
  217.          WriteData();
  218.       }
  219.    else
  220.       {
  221.          ReadData();
  222.       }
  223. }
  224.  
  225.  
  226. Init()
  227. {
  228.    text_buf = NULL;
  229.    lson     = NULL;
  230.    rson     = NULL;
  231.    dad      = NULL;
  232.  
  233.    if (!(ReadPort = CreatePort(0L, 0L)))
  234.       {
  235.          puts("Couldn't create read port");
  236.          exit (1);
  237.       }
  238.  
  239.    if (!(WritePort = CreatePort(0L, 0L)))
  240.       {
  241.          puts("Couldn't create write port");
  242.          CleanUp();
  243.          exit (1);
  244.       }
  245.  
  246.    if (!(ReadMsg = (struct IORequest *) CreateExtIO(ReadPort, (long) sizeof(struct IOExtTD))))
  247.       {
  248.          puts("Couldn't create i/o read request");
  249.          CleanUp();
  250.          exit (1);
  251.       }
  252.  
  253.    if (!(WriteMsg = (struct IORequest *) CreateExtIO(WritePort, (long) sizeof(struct IOExtTD))))
  254.       {
  255.          puts("Couldn't create i/o write request");
  256.          CleanUp();
  257.          exit (1);
  258.       }
  259.  
  260.    ReadMsg->iotd_Req.io_Command = ETD_READ;
  261.    WriteMsg->iotd_Req.io_Command = ETD_WRITE;
  262.  
  263.    if (OpenDevice(TD_NAME, Unit, (struct IORequest *) ReadMsg, 0L))
  264.       {
  265.          puts("Couldn't open trackdisk.device for reading");
  266.          CleanUp();
  267.          exit (1);
  268.       }
  269.  
  270.    if (OpenDevice(TD_NAME, Unit, (struct IORequest *) WriteMsg, 0L))
  271.       {
  272.          puts("Couldn't open trackdisk.device for writing");
  273.          CleanUp();
  274.          exit (1);
  275.       }
  276.  
  277.    if (!(DataBlock = AllocMem((ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH, MEMF_PUBLIC)))
  278.       {
  279.          puts("Couldn't allocate trackdisk memory buffer");
  280.          CleanUp();
  281.          exit (1);
  282.       }
  283.  
  284.    if (!(NewBlock = AllocMem((ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH, MEMF_PUBLIC)))
  285.       {
  286.          puts("Couldn't allocate trackdisk memory buffer");
  287.          CleanUp();
  288.          exit (1);
  289.       }
  290.  
  291.    if (!(TrackdiskBlock = AllocMem((ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH, MEMF_CHIP)))
  292.       {
  293.          puts("Couldn't allocate trackdisk memory buffer");
  294.          CleanUp();
  295.          exit (1);
  296.       }
  297.  
  298.    if (!(iotd_SecLabel = AllocMem((ULONG) LABEL_LENGTH, MEMF_CHIP)))
  299.       {
  300.          puts("Couldn't allocate trackdisk extended memory buffer");
  301.          CleanUp();
  302.          exit (1);
  303.       }
  304.  
  305.    if (!(text_buf = AllocMem((ULONG) (N + F - 1), MEMF_PUBLIC)))
  306.       {
  307.          puts("Out of memory");
  308.          CleanUp();
  309.          exit (1);
  310.       }
  311.  
  312.    if (!(lson = AllocMem((ULONG) (N + 1) * (ULONG) (sizeof(short)), MEMF_PUBLIC)))
  313.       {
  314.          puts("Out of memory");
  315.          CleanUp();
  316.          exit (1);
  317.       }
  318.  
  319.    if (!(rson = AllocMem((ULONG) (N + 257) * (ULONG) (sizeof(short)), MEMF_PUBLIC)))
  320.       {
  321.          puts("Out of memory");
  322.          CleanUp();
  323.          exit (1);
  324.       }
  325.  
  326.    if (!(dad = AllocMem((ULONG) (N + 1) * (ULONG) (sizeof(short)), MEMF_PUBLIC)))
  327.       {
  328.          puts("Out of memory");
  329.          CleanUp();
  330.          exit (1);
  331.       }
  332. }
  333.  
  334.  
  335. Archive(USHORT Track, ULONG DataSize)
  336. {
  337.    UBYTE            *OutBuffer;
  338.    UBYTE             CanSetBuffer;
  339.    ULONG             CurrentPosition;
  340.    ULONG             AfterEncodeLength;
  341.    ULONG             TotalEncodeLength;
  342.    BPTR              outfp;
  343.  
  344.    if (OutBuffer = AllocMem((ULONG) OUT_BUFFER_SIZE, MEMF_PUBLIC))
  345.       {
  346.          CanSetBuffer = 1;
  347.       }
  348.    else
  349.       {
  350.          CanSetBuffer = 0;
  351.       }
  352.  
  353.    CurrentPosition = GetFileLength(FileName);
  354.  
  355.    /* Lhwarp to a file; this way, if the output is larger than the input */
  356.    /* we won't crash the machine */
  357.    if (!(outfile = fopen(FileName, "a+b")))
  358.       {
  359.          printf("Couldn't open temporary file for output\n");
  360.  
  361.          if (CanSetBuffer)
  362.             {
  363.                FreeMem(OutBuffer, (ULONG) OUT_BUFFER_SIZE);
  364.             }
  365.  
  366.          CleanUp();
  367.          exit (1);
  368.       }
  369.  
  370.    if (CanSetBuffer)
  371.       {
  372.          setvbuf(outfile, OutBuffer, _IOFBF, (long) OUT_BUFFER_SIZE);
  373.       }
  374.  
  375.    /* Write out a dummy file compression header */
  376.    fwrite(&CHeader102, sizeof(struct CompHeader102), 1, outfile);
  377.  
  378.    Encode((ULONG) (DataSize));
  379.  
  380.    fclose(outfile);
  381.  
  382.    if (CanSetBuffer)
  383.       {
  384.          FreeMem(OutBuffer, (ULONG) OUT_BUFFER_SIZE);
  385.       }
  386.  
  387.    AfterEncodeLength = GetFileLength(FileName);
  388.    TotalEncodeLength = AfterEncodeLength - CurrentPosition - sizeof(struct CompHeader102);
  389.  
  390.    if (!(outfp = (BPTR) Open(FileName, (long) MODE_READWRITE)))
  391.       {
  392.          printf("Couldn't open temporary file for output\n");
  393.  
  394.          if (CanSetBuffer)
  395.             {
  396.                FreeMem(OutBuffer, (ULONG) OUT_BUFFER_SIZE);
  397.             }
  398.  
  399.          CleanUp();
  400.          exit (1);
  401.       }
  402.  
  403.    /* Seek back to the CompHeader section */
  404.    Seek((BPTR) outfp, (long) CurrentPosition, (long) OFFSET_BEGINNING);
  405.  
  406.    CHeader102.CompressedLength = TotalEncodeLength;
  407.    CHeader102.FullLength       = DataSize;
  408.    CHeader102.TrackNumber      = (UBYTE) Track;
  409.    CHeader102.CompressionType  = COMPTYPE_LHARC;
  410.    CHeader102.DataType         = DATATYPE_NORMAL;
  411.  
  412.    /* Checksum the block */
  413.    CHeader102.CheckSum = (ULONG) DoSum(NewBlock, (ULONG) CHeader102.FullLength);
  414.  
  415.    /* Write it to disk */
  416.    Write((BPTR) outfp, &CHeader102, (long) sizeof(struct CompHeader102));
  417.  
  418.    /* Close the file */
  419.    Close((BPTR) outfp);
  420. }
  421.  
  422.  
  423. WriteData()
  424. {
  425.    ULONG  Track;
  426.    UBYTE *TextMemory;
  427.    UBYTE *TextCompMemory;
  428.    UBYTE *ExtendedDataBlock;
  429.    ULONG  CheckSum;
  430.    ULONG  TracksWritten = 0L;
  431.  
  432.    printf("\nLHWARP %d.%d%d - Amiga disk tracker - Written by Jonathan Forbes @ 1:250/642\n", (UBYTE) MAJOR_VERSION, (UBYTE) MINOR_VERSION, (UBYTE) DECIMAL_VERSION);
  433.    puts("Copyright © Xenomiga Technology, 1990.\n");
  434.    printf("Writing to disk in drive %ld from file %s\n", Unit, FileName);
  435.  
  436.    /* Set up the write request */
  437.    WriteMsg->iotd_Req.io_Command = ETD_FORMAT;
  438.  
  439.    if (!(infile = fopen(FileName, "r")))
  440.       {
  441.          printf("Cannot open %s for input\n", FileName);
  442.          CleanUp();
  443.          exit (1);
  444.       }
  445.  
  446.    /* Read the Warp header */
  447.    fread(&WHeader, sizeof(struct WarpHeader), 1, infile);
  448.  
  449.    /* What version of Lhwarp was used to compress the disk? */
  450.    if (WHeader.MajorVersion == 1 && WHeader.MinorVersion == 0 && WHeader.DecimalVersion == 1)
  451.       {
  452.          printf("Disk was compressed using Lhwarp 1.01\n\n");
  453.          Version101 = 1;
  454.       }
  455.    else
  456.       {
  457.          printf("Disk was compressed using Lhwarp %d.%d%d\n\n", WHeader.MajorVersion, WHeader.MinorVersion, WHeader.DecimalVersion);
  458.          Version101 = 0;
  459.       }
  460.  
  461.    if ((WHeader.MajorVersion > MAJOR_VERSION) ||
  462.        (WHeader.MajorVersion == MAJOR_VERSION && WHeader.MinorVersion > MINOR_VERSION))
  463.       {
  464.          printf("Sorry, this file was Lhwarp'd with Lhwarp V%d%d.%d\n",
  465.             WHeader.MajorVersion, WHeader.MinorVersion, WHeader.DecimalVersion);
  466.  
  467.          printf("You are using Lhwarp V%d%d.%d\n",
  468.             MAJOR_VERSION, MINOR_VERSION, DECIMAL_VERSION);
  469.  
  470.          CleanUp();
  471.          exit(1);
  472.       }
  473.  
  474.    if (WHeader.TextLength)
  475.       {
  476.          if (!(TextMemory = AllocMem((ULONG) WHeader.TextLength+1, MEMF_PUBLIC)))
  477.             {
  478.                printf("Insufficient memory (%ld bytes required) to read compressed text\n", (ULONG) WHeader.TextLength+1);
  479.                CleanUp();
  480.                exit(1);
  481.             }
  482.  
  483.          if (!(TextCompMemory = AllocMem((ULONG) WHeader.CompressedTextLength, MEMF_PUBLIC)))
  484.             {
  485.                printf("Insufficient memory (%ld bytes required) to decompress text\n", (ULONG) WHeader.CompressedTextLength);
  486.                FreeMem(TextMemory, (ULONG) WHeader.TextLength+1);
  487.                CleanUp();
  488.                exit(1);
  489.             }
  490.  
  491.          fread(TextCompMemory, (ULONG) WHeader.CompressedTextLength, 1, infile);
  492.  
  493.          FilePosition = (UBYTE *) TextCompMemory;
  494.  
  495.          /* Arbitrary number; just make it greater than TextLength */
  496.          EndOfFilePosition = (UBYTE *) ( ((UBYTE *) TextCompMemory) + (WHeader.CompressedTextLength));
  497.  
  498.          PutFilePosition = (UBYTE *) TextMemory;
  499.  
  500.          Decode((ULONG) WHeader.TextLength);
  501.  
  502.          /* Make sure the text has a null terminator */
  503.          TextMemory[WHeader.TextLength] = 0;
  504.  
  505.          puts("\n----\n");
  506.          puts(TextMemory);
  507.          puts("----\n");
  508.  
  509.          FreeMem(TextMemory, (ULONG) WHeader.TextLength+1);
  510.          FreeMem(TextCompMemory, (ULONG) WHeader.CompressedTextLength);
  511.       }
  512.  
  513.    /* Start writing tracks */
  514.    for (;;)
  515.       {
  516.          if (Version101)
  517.             {
  518.                if (!(fread(&CHeader101, sizeof(struct CompHeader101), 1, infile)))
  519.                   {
  520.                      break;
  521.                   }
  522.             }
  523.          else
  524.             {
  525.                if (!(fread(&CHeader102, sizeof(struct CompHeader102), 1, infile)))
  526.                   {
  527.                      break;
  528.                   }
  529.             }
  530.  
  531.          FilePosition = (UBYTE *) DataBlock;
  532.          PutFilePosition = (UBYTE *) NewBlock;
  533.  
  534.          if (Version101)
  535.             {
  536.                EndOfFilePosition = (UBYTE *) ( ((UBYTE *) DataBlock) + CHeader101.CompressedLength);
  537.                fread(DataBlock, (long) CHeader101.CompressedLength, 1, infile);
  538.                Decode((ULONG) CHeader101.FullLength);
  539.  
  540.                Track = (ULONG) CHeader101.TrackNumber;
  541.             }
  542.          else
  543.             {
  544.                EndOfFilePosition = (UBYTE *) ( ((UBYTE *) DataBlock) + CHeader102.CompressedLength);
  545.                fread(DataBlock, (long) CHeader102.CompressedLength, 1, infile);
  546.                Decode((ULONG) CHeader102.FullLength);
  547.  
  548.                CheckSum = (ULONG) DoSum(NewBlock, (ULONG) CHeader102.FullLength);
  549.  
  550.                if (CheckSum != CHeader102.CheckSum)
  551.                   {
  552.                      printf("Warning: Track %ld fails checksum\n", Track);
  553.                   }
  554.  
  555.                Track = (ULONG) CHeader102.TrackNumber;
  556.             }
  557.  
  558.          ExtendedDataBlock = (UBYTE *) ( ((UBYTE *) NewBlock) + ((ULONG) TRACK_SIZE));
  559.  
  560.          CopyMem(ExtendedDataBlock, (UBYTE *) &iotd_SecLabel[0], (ULONG) LABEL_LENGTH);
  561.  
  562.          if (!Track)
  563.             {
  564.                puts("Disk contains the following bootblock:\n");
  565.                DisplayBootBlock(NewBlock);
  566.             }
  567.  
  568.          /* Copy data into CHIP RAM */
  569.          CopyMem(NewBlock, TrackdiskBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH);
  570.  
  571.          WriteMsg->iotd_Req.io_Offset = (long) TRACK_SIZE * Track;
  572.          WriteMsg->iotd_Req.io_Data   = (APTR) TrackdiskBlock;
  573.          WriteMsg->iotd_Req.io_Length = (long) TRACK_SIZE;
  574.          WriteMsg->iotd_SecLabel      = &iotd_SecLabel[0];
  575.          WriteMsg->iotd_Count         = 0xFFFFFFFF;
  576.  
  577.          printf("Writing track %2ld", (ULONG) (Track));
  578.          fflush(stdout);
  579.  
  580.          if (DoIO((struct IORequest *) WriteMsg))
  581.             {
  582.                fclose(infile);
  583.                printf("Fatal error writing to disk in unit %ld -terminating\n\n", Unit);
  584.                MotorOff();
  585.                CleanUp();
  586.                exit (1);
  587.             }
  588.  
  589.          printf("\nA");
  590.          fflush(stdout);
  591.  
  592.          TracksWritten++;
  593.       }
  594.  
  595.    MotorOff();
  596.    WriteMsg->iotd_Req.io_Length  = 0L;
  597.    WriteMsg->iotd_Req.io_Command = CMD_FLUSH;
  598.    DoIO((struct IORequest *) WriteMsg);
  599.  
  600.    fclose(infile);
  601.  
  602.    printf("\n\nFinished writing %ld tracks\n\n", TracksWritten);
  603.    printf("Please remove and re-insert destination disk, to use\n\n");
  604.  
  605.    CleanUp();
  606. }
  607.  
  608.  
  609. MotorOff()
  610. {
  611.    WriteMsg->iotd_Req.io_Length  = 0L;
  612.    WriteMsg->iotd_Req.io_Command = TD_MOTOR;
  613.    DoIO((struct IORequest *) WriteMsg);
  614. }
  615.  
  616.  
  617. DisplayBootBlock(UBYTE *Data)
  618. {
  619.    char           Line[76];
  620.    UBYTE          i;
  621.    register UBYTE j;
  622.    register UBYTE c;
  623.  
  624.    /* End of the line to be displayed */
  625.    Line[73] = 10;
  626.    Line[74] = 13;
  627.    Line[75] = 0;
  628.  
  629.    for (i=0; i<14; i++)
  630.       {
  631.          for (j=0; j<73; j++)
  632.             {
  633.                c = *((UBYTE *) ( ((UBYTE *) Data) + (i * 64) + j));
  634.  
  635.                if (c < 32 || c > 126)
  636.                   {
  637.                      c = '.';
  638.                   }
  639.  
  640.                Line[j] = c;
  641.             }
  642.  
  643.          printf(Line);
  644.       }
  645.  
  646.    puts("");
  647. }
  648.  
  649.  
  650. ReadData()
  651. {
  652.    ULONG  AfterEncodeLength;
  653.    ULONG  TotalEncodeLength;
  654.    ULONG  TextLength;
  655.    ULONG  i;
  656.    ULONG  FileLength;
  657.    ULONG  OriginalLength = 0L;
  658.    BPTR   OutputFile;
  659.    ULONG  Error;
  660.    ULONG  DataSize;
  661.    ULONG  OnlyDataSize;
  662.    FILE  *TextInFile;
  663.    UBYTE *TextMemory;
  664.    UBYTE *ExtendedDataBlock;
  665.  
  666.    printf("\nLHWARP %d.%d%d - Amiga disk tracker - Written by Jonathan Forbes @ 1:250/642\n", (UBYTE) MAJOR_VERSION, (UBYTE) MINOR_VERSION, (UBYTE) DECIMAL_VERSION);
  667.    puts("Copyright © Xenomiga Technology, 1990.\n");
  668.    printf("Reading from disk in drive %ld to file %s\n", Unit, FileName);
  669.  
  670.    /* Set up the read request */
  671.    ReadMsg->iotd_Req.io_Command = ETD_READ;
  672.    ReadMsg->iotd_Count          = 0xFFFFFFFF;
  673.  
  674.    /* If we start at track zero, check the boot block */
  675.    if (!StartTrack)
  676.       {
  677.          ReadMsg->iotd_Req.io_Offset = (long) 0L;
  678.          ReadMsg->iotd_Req.io_Data   = (APTR) TrackdiskBlock;
  679.  
  680.          /* Only get the first two sectors */
  681.          ReadMsg->iotd_Req.io_Length = (long) 1024L;
  682.  
  683.          if (Error = DoIO((struct IORequest *) ReadMsg))
  684.             {
  685.                printf("Error %d reading from trackdisk.device\n", Error);
  686.                CleanUp();
  687.                exit (1);
  688.             }
  689.  
  690.          printf("\nBoot block of floppy disk in drive %d:\n\n", Unit);
  691.          DisplayBootBlock(TrackdiskBlock);
  692.       }
  693.  
  694.    if (AppendTextFile)
  695.       {
  696.          TextLength = GetFileLength(TextFileName);
  697.  
  698.          if (!TextLength)
  699.             {
  700.                puts("Text file missing or zero length\n");
  701.                CleanUp();
  702.                exit (1);
  703.             }
  704.  
  705.          WHeader.TextLength = TextLength;
  706.       }
  707.    else
  708.       {
  709.          WHeader.TextLength = 0L;
  710.       }
  711.  
  712.    /* Build the Warp header */
  713.    WHeader.StartTrack = StartTrack;
  714.    WHeader.EndTrack   = EndTrack;
  715.  
  716.    /* Version 1.03 */
  717.    WHeader.MajorVersion = (UBYTE) MAJOR_VERSION;
  718.    WHeader.MinorVersion = (UBYTE) MINOR_VERSION;
  719.    WHeader.DecimalVersion = (UBYTE) DECIMAL_VERSION;
  720.  
  721.    /* Write out the Warp header */
  722.    if (!(OutputFile = Open(FileName, MODE_NEWFILE)))
  723.       {
  724.          printf("Couldn't open output file\n");
  725.          CleanUp();
  726.          exit (1);
  727.       }
  728.  
  729.    Write(OutputFile, &WHeader, (long) sizeof(struct WarpHeader));
  730.    Close(OutputFile);
  731.  
  732.    if (AppendTextFile)
  733.       {
  734.          printf("Compressing text ... ");
  735.          fflush(stdout);
  736.  
  737.          if (!(TextInFile = fopen(TextFileName, "r")))
  738.             {
  739.                printf("Can't open %s for input\n", TextInFile);
  740.                CleanUp();
  741.                exit(1);
  742.             }
  743.  
  744.          if (!(TextMemory = AllocMem((ULONG) TextLength, MEMF_PUBLIC)))
  745.             {
  746.                puts("Couldn't allocate text memory buffer");
  747.                CleanUp();
  748.                exit(1);
  749.             }
  750.  
  751.          fread(TextMemory, (ULONG) TextLength, 1, TextInFile);
  752.          fclose(TextInFile);
  753.  
  754.          if (!(outfile = fopen(FileName, "a")))
  755.             {
  756.                printf("Can't open %s for append\n", FileName);
  757.                FreeMem(TextMemory, (ULONG) TextLength);
  758.                CleanUp();
  759.                exit(1);
  760.             }
  761.  
  762.          FilePosition = (UBYTE *) TextMemory;
  763.          EndOfFilePosition = (UBYTE *) ( ((UBYTE *) TextMemory) + (TextLength));
  764.  
  765.          Encode((ULONG) (TextLength));
  766.          fclose(outfile);
  767.  
  768.          FreeMem(TextMemory, (ULONG) TextLength);
  769.  
  770.          AfterEncodeLength = GetFileLength(FileName);
  771.          TotalEncodeLength = AfterEncodeLength - (ULONG) sizeof(struct WarpHeader);
  772.  
  773.          WHeader.CompressedTextLength = TotalEncodeLength;
  774.  
  775.          if (!(outfile = fopen(FileName, "r+w")))
  776.             {
  777.                printf("Can't open %s for append\n", FileName);
  778.                CleanUp();
  779.                exit(1);
  780.             }
  781.  
  782.          fwrite(&WHeader, sizeof(struct WarpHeader), 1, outfile);
  783.          fclose(outfile);
  784.  
  785.          printf("done\n\n");
  786.       }
  787.  
  788.    /* Start reading tracks */
  789.    for (i = StartTrack; i <= EndTrack; i++)
  790.       {
  791.          DataSize = (ULONG) TRACK_SIZE + (ULONG) (NUMSECS * NUM_HEADS * 16);
  792.          OnlyDataSize = (ULONG) TRACK_SIZE;
  793.          ExtendedDataBlock = (UBYTE *) ( ((UBYTE *) NewBlock) + ((ULONG) OnlyDataSize));
  794.  
  795.          ReadMsg->iotd_Req.io_Offset = (long) TRACK_SIZE * i;
  796.          ReadMsg->iotd_Req.io_Data   = (APTR) TrackdiskBlock;
  797.          ReadMsg->iotd_Req.io_Length = (long) TRACK_SIZE;
  798.          ReadMsg->iotd_SecLabel      = &iotd_SecLabel[0];
  799.          ReadMsg->iotd_Count         = 0xFFFFFFFF;
  800.  
  801.          printf("Reading track %2ld ...            D", (ULONG) (i));
  802.  
  803.          fflush(stdout);
  804.  
  805.          DoIO((struct IORequest *) ReadMsg);
  806.  
  807.          printf("compressing");
  808.          fflush(stdout);
  809.  
  810.          /* Copy data out of CHIP RAM */
  811.          CopyMem(TrackdiskBlock, NewBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH);
  812.          CopyMem((UBYTE *) &iotd_SecLabel[0], (UBYTE *) ExtendedDataBlock, (ULONG) NUMSECS * NUM_HEADS * 16);
  813.  
  814.          FilePosition = (UBYTE *) NewBlock;
  815.          EndOfFilePosition = (UBYTE *) ( ((UBYTE *) NewBlock) + (DataSize));
  816.  
  817.          Archive(i, DataSize);
  818.  
  819.          OriginalLength += (DataSize);
  820.  
  821.          printf("\nA");
  822.       }
  823.  
  824.    ReadMsg->iotd_Req.io_Length  = 0;
  825.    ReadMsg->iotd_Req.io_Command = TD_MOTOR;
  826.    DoIO((struct IORequest *) ReadMsg);
  827.  
  828.    FileLength = GetFileLength(FileName);
  829.  
  830.    printf("\n\nFinished reading tracks %d to %d (%d total)\n", WHeader.StartTrack, WHeader.EndTrack, WHeader.EndTrack - WHeader.StartTrack + 1);
  831.    printf(" Input file: %ld bytes\n", OriginalLength);
  832.    printf("Output file: %ld bytes\n\n", FileLength);
  833.  
  834.    CleanUp();
  835. }
  836.  
  837.  
  838. CleanUp()
  839. {
  840.    if (ReadMsg)
  841.       {
  842.          CloseDevice((struct IORequest *) ReadMsg);
  843.          DeleteExtIO((struct IORequest *) ReadMsg, (long) sizeof(struct IOExtTD));
  844.       }
  845.  
  846.    if (WriteMsg)
  847.       {
  848.          CloseDevice((struct IORequest *) WriteMsg);
  849.          DeleteExtIO((struct IORequest *) WriteMsg, (long) sizeof(struct IOExtTD));
  850.       }
  851.  
  852.    if (ReadPort)
  853.       {
  854.          DeletePort(ReadPort);
  855.       }
  856.  
  857.    if (WritePort)
  858.       {
  859.          DeletePort(WritePort);
  860.       }
  861.  
  862.    if (DataBlock)
  863.       {
  864.          FreeMem(DataBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH);
  865.       }
  866.  
  867.    if (NewBlock)
  868.       {
  869.          FreeMem(NewBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH);
  870.       }
  871.  
  872.    if (TrackdiskBlock)
  873.       {
  874.          FreeMem(TrackdiskBlock, (ULONG) TRACK_SIZE + (ULONG) LABEL_LENGTH);
  875.       }
  876.  
  877.    if (iotd_SecLabel)
  878.       {
  879.          FreeMem(iotd_SecLabel, (ULONG) LABEL_LENGTH);
  880.       }
  881.  
  882.    if (text_buf)
  883.       {
  884.          FreeMem(text_buf, (ULONG) (N + F - 1));
  885.       }
  886.  
  887.    if (lson)
  888.       {
  889.          FreeMem(lson, (ULONG) (N + 1) * (ULONG) (sizeof(short)));
  890.       }
  891.  
  892.    if (rson)
  893.       {
  894.          FreeMem(rson, (ULONG) (N + 257) * (ULONG) (sizeof(short)));
  895.       }
  896.  
  897.    if (dad)
  898.       {
  899.          FreeMem(dad, (ULONG) (N + 1) * (ULONG) (sizeof(short)));
  900.       }
  901. }
  902.  
  903.  
  904. Title()
  905. {
  906.    printf("\nLHWARP %d.%d%d - Amiga disk tracker - Written by Jonathan Forbes @ 1:250/642\n", (UBYTE) MAJOR_VERSION, (UBYTE) MINOR_VERSION, (UBYTE) DECIMAL_VERSION);
  907.    puts("Copyright © Xenomiga Technology, 1990.\n");
  908.  
  909.    puts("Usage: LHWARP <Read|Write> <Unit> <Filename> <StartTrack> <EndTrack> <TextFile>\n");
  910.  
  911.    puts("<Unit>       - Drive number (0 for internal, 1 ... 3 for external)");
  912.    puts("<Filename>   - Output|Input filename");
  913.    puts("<StartTrack> - Track number (0 ... 79) [only valid in read mode]");
  914.    puts("<EndTrack>   - Track number (0 ... 79) [only valid in read mode]");
  915.    puts("<TFile>      - Append text in <TextFile> to output file [optional]\n");
  916. }
  917.  
  918.  
  919. ULONG GetFileLength(register char *FileToOpen)
  920. {
  921.    register ULONG                 FileLength;
  922.    register ULONG                 lock;
  923.    register struct FileInfoBlock *fileinfo;
  924.  
  925.    if (access(FileToOpen, 0))
  926.       {
  927.          return (0L);
  928.       }
  929.  
  930.    fileinfo = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock),
  931.                MEMF_CLEAR | MEMF_PUBLIC);
  932.  
  933.    if (!fileinfo)
  934.       {
  935.          printf("\n\r\n\rUtterly fatal error: Out of memory\n\r\n\r");
  936.          return (NULL);
  937.       }
  938.  
  939.    lock     = (ULONG) Lock(FileToOpen, ACCESS_READ);
  940.  
  941.    if (!lock)
  942.       {
  943.          FreeMem(fileinfo, sizeof(struct FileInfoBlock));
  944.          return (NULL);
  945.       }
  946.  
  947.    Examine(lock, fileinfo);
  948.    FileLength = fileinfo->fib_Size;
  949.    UnLock(lock);
  950.    FreeMem(fileinfo, sizeof(struct FileInfoBlock));
  951.    return (FileLength);
  952. }
  953.  
  954.  
  955. /* If the user presses ^C */
  956. int CXBRK()
  957. {
  958.    if (WriteMsg)
  959.       {
  960.          WriteMsg->iotd_Req.io_Length  = 0L;
  961.          WriteMsg->iotd_Req.io_Command = TD_MOTOR;
  962.          DoIO((struct IORequest *) WriteMsg);
  963.       }
  964.  
  965.    if (ReadMsg)
  966.       {
  967.          ReadMsg->iotd_Req.io_Length  = 0L;
  968.          ReadMsg->iotd_Req.io_Command = TD_MOTOR;
  969.          DoIO((struct IORequest *) ReadMsg);
  970.       }
  971.  
  972.    CleanUp();
  973.    return (-1);
  974. }
  975.  
  976.  
  977. ULONG DoSum(UBYTE *Block, ULONG Length)
  978. {
  979.    register ULONG Sum = 0;
  980.    register ULONG i;
  981.  
  982.    for (i = 0; i < Length; i++)
  983.       {
  984.          Sum = Sum + Block[i];
  985.       }
  986.  
  987.    return (Sum);
  988. }
  989.